package me.android.library.ui.impl;

import android.os.Bundle;
import android.util.Log;

import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import com.google.common.base.Objects;
import com.google.common.base.Strings;

import lombok.Getter;
import me.android.library.ui.UiService;
import me.android.library.ui.api.LayoutLoader;
import me.android.library.ui.api.Page;
import me.android.library.ui.config.FormInfo;
import me.android.library.ui.event.MenuToggledEvent;
import me.android.library.ui.event.PageChangedEvent;
import me.android.library.utils.android.SoftInputUtil;
import mylab.utils.common.guava.AsyncEventUtil;

public class FormManager {

    @Getter
    private final String formKey;

    @Getter
    private final String homeKey;
    @Getter
    private String currrentPageKey;
    @Getter
    private final LayoutLoader loader;

    @Getter
    private FragmentActivity activity;
    private FragmentManager fragmentManager;
    private boolean isShownMenu;
    private final FragmentManager.OnBackStackChangedListener backStackListener = this::onFragmentChanged;

    public FormManager(FormInfo formInfo) {
        formKey = formInfo.getId();
        homeKey = formInfo.getHome();
        loader = formInfo.get();
    }

    public Page getCurrentPage() {
        return getCachedPage(currrentPageKey);
    }

    public boolean isHome() {
        return isHomePage(currrentPageKey);
    }

    public boolean isHomePage(String pageKey) {
        return homeKey.equals(pageKey);
    }

    public boolean isShownMenu() {
        return isShownMenu;
    }

    public boolean toggleMenu() {
        isShownMenu = loader.toggleMenu();
        AsyncEventUtil.postEvent(new MenuToggledEvent(loader, isShownMenu));
        return isShownMenu;
    }

    public void attachActivity(FragmentActivity main, String firstPageKey) {

        this.activity = main;
        fragmentManager = this.activity.getSupportFragmentManager();

        int backStackCount = fragmentManager.getBackStackEntryCount();
        for (int i = 0; i < backStackCount; i++) {
            fragmentManager.popBackStackImmediate();
        }

        fragmentManager.removeOnBackStackChangedListener(backStackListener);
        fragmentManager.addOnBackStackChangedListener(backStackListener);

        Log.i("app", "stack count of page:" + fragmentManager.getBackStackEntryCount());
        loader.layout(main);

        postPage(homeKey, null);
        if (!Strings.isNullOrEmpty(firstPageKey)) {
            postPage(firstPageKey, null);
        }

    }

    public void detachActivity() {
    }

    synchronized public void postPage(String pageKey) {
        postPage(pageKey, null);
    }

    synchronized public void postPage(String pageKey, Bundle args) {
        loader.switchContent(pageKey, args);
    }

    synchronized public void popBack() {

        SoftInputUtil.hide(activity);

        int count = fragmentManager.getBackStackEntryCount();
        if (count > 1) {
            Log.d("fragment", String.format("page removed: %s", currrentPageKey));

            FragmentTransaction ft = fragmentManager.beginTransaction();
            Page page = getCachedPage(currrentPageKey);
            if (page instanceof Fragment) {
                removePage(currrentPageKey, ft, (Fragment) page);
            }
            fragmentManager.popBackStack();
            ft.commitAllowingStateLoss();

        } else {
            activity.finish();
        }
    }

    synchronized public void returnHome() {

        if (isHome())
            return;

        int count = fragmentManager.getBackStackEntryCount();

        // 回退至主界面，并释放其它界面
        if (count > 0) {
            FragmentTransaction ft = fragmentManager.beginTransaction();
            String frmTag;
            for (int i = count - 1; i >= 0; i--) {
                frmTag = fragmentManager.getBackStackEntryAt(i).getName();
                if (Strings.isNullOrEmpty(frmTag))
                    continue;
                if (Objects.equal(homeKey, frmTag))
                    continue;

                Fragment frm = fragmentManager.findFragmentByTag(frmTag);
                removePage(frmTag, ft, frm);
            }

            fragmentManager.popBackStack(homeKey, 0);  // 主界面不弹出，仍留在堆栈中
            ft.commitAllowingStateLoss();
        }

        // 若堆栈中无主界面，则清空堆栈，并加载主界面
        if (fragmentManager.findFragmentByTag(homeKey) == null) {
            fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
            postPage(homeKey);
        }
    }

    private void onFragmentChanged() {

        SoftInputUtil.hide(activity);

        int count = fragmentManager.getBackStackEntryCount();
        Log.d("fragment", String.format("page count: %s", count));

        if (count == 0)
            return;

        String pageKey = fragmentManager.getBackStackEntryAt(count - 1).getName();
        Log.d("fragment", String.format("page current: %s", pageKey));

        loader.onPageInActivated(currrentPageKey);
        Page prePage = getCachedPage(currrentPageKey);
        if (prePage != null) {
            prePage.onPageInActivated();
        }

        currrentPageKey = pageKey;
        loader.onPageActivated(currrentPageKey);
        Page curPage = getCachedPage(currrentPageKey);
        curPage.onPageActivated();

        AsyncEventUtil.postEvent(new PageChangedEvent(loader, currrentPageKey));
    }

    private Page getCachedPage(String pageKey) {
        return UiService.getInstance().getPage(pageKey);
    }

    private void removePage(String pageKey, FragmentTransaction ft, Fragment frm) {
        if (frm != null) {
            if (frm instanceof Page) {
                ((Page) frm).onPageInActivated();
            }

            ft.remove(frm);
        }

        UiService.getInstance().removePage(pageKey);
    }
}
